/*
 * Copyright (C) 2000-2008 Jens Nixdorf and various contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies of the Software, its documentation and marketing & publicity
 * materials, and acknowledgment shall be given in the documentation, materials
 * and software packages that this Software was used.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package org.mopore.jat.core.fadingmessage;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

import org.mopore.jat.core.messaging.Message;
import org.mopore.jat.util.ImageService;
import org.mopore.jat.util.TextService;

public class Content {
	
	/**
	 * 
	 */
	private static final String BLANK = " ";

	/**
	 * 
	 */
	private static final int HORIZONTAL_IMAGE_OFFSET = 2;

	/**
	 * 
	 */
	private static final int MAX_IMAGE_HEIGHT = 46;

	/**
	 * 
	 */
	private static final int MAX_IMAGE_WIDTH = 69;

	private static final int BUTTON_OFFSET = 16;

	private static final int MAX_TEXT_WIDTH = 232;

	private boolean optimized;
	
	private String title;
	
	private TextLine[] lines;

	private final Font titleFont;

	private final Font textFont;
	
	private BufferedImage scaledImage;

	private String text;
	
	private int[] lineWidths;


	/**
	 * @param message
	 */
	public Content(Message message) {
		optimized = false; 
		titleFont = new Font("Arial", Font.BOLD, 14);
		textFont = titleFont.deriveFont(Font.PLAIN, 12);
		this.title = message.getTitle();
		this.text = message.getText();
		
		BufferedImage image = message.getImage();
		lineWidths = new int[] {
				MAX_TEXT_WIDTH, MAX_TEXT_WIDTH, MAX_TEXT_WIDTH, MAX_TEXT_WIDTH };
		if ( image != null ) {
			scaledImage = 
				ImageService.scaleWithContraints( image, MAX_IMAGE_WIDTH, MAX_IMAGE_HEIGHT );
			defineMaxTextLineWidths( scaledImage );
		}
		
	}


	private void defineMaxTextLineWidths(BufferedImage image) {
		int[] maxImageHeightForMaxLineWidths = {0, 10, 22, 34};
		int imageHeight = image.getHeight();
		int imageWidth = image.getWidth();
		for ( int i = 0; i < 4; i++) {
			int maxHeight = maxImageHeightForMaxLineWidths[i];
			
			int lineWidth;
			if ( imageHeight <= maxHeight ) {
				lineWidth = MAX_TEXT_WIDTH;
			}
			else {
				lineWidth = MAX_TEXT_WIDTH - 
								HORIZONTAL_IMAGE_OFFSET - imageWidth;
			}
			
			lineWidths[i] = lineWidth;
		}
	}
	
	
	public void assertOptimization( Graphics2D graphics2D ){
		if ( optimized == false ){
			optimize( graphics2D );
			optimized = true;
		}
	}
	
	private void optimize(Graphics2D graphics2D) {
		
		FontMetrics titleMetrics = graphics2D.getFontMetrics( titleFont );
		title = TextService.bringTextToWidth( titleMetrics, title, 
				MAX_TEXT_WIDTH - BUTTON_OFFSET );
		
		FontMetrics metrics = graphics2D.getFontMetrics( textFont );
		StringTokenizer tokenizer = new StringTokenizer( text, BLANK);
		List<TextLine> lineList = new LinkedList<TextLine>();
		final int blankWidth = metrics.stringWidth( BLANK );
		
		int lineIndex = 0;
		int maxLineWidth = lineWidths[ lineIndex ];
		String line = "";
		
		String token;
		while ( tokenizer.hasMoreTokens() ) {
			token = tokenizer.nextToken();
			
			int lineWidth = metrics.stringWidth( line );
			int tokenWidth = metrics.stringWidth( token );
			
			int candidateWidth = lineWidth + blankWidth + tokenWidth;
			if ( candidateWidth <= maxLineWidth ) {
				if ( line.length() > 0 ) {
					line = line + BLANK + token;
				}
				else {
					line = token;
				}
				
				boolean regularEnd = !tokenizer.hasMoreElements();
				if ( regularEnd ) {
					// regular end;
					int x = MAX_TEXT_WIDTH - maxLineWidth + 10;
					
					
					TextLine textLine = new TextLine( line, x );
					lineList.add( textLine );
					break;
				}
			}
			else {
				// end of line reached;
				
				boolean noMoreLines = lineIndex == 3;
				if ( noMoreLines ) {
					int widthLeft = maxLineWidth - blankWidth - lineWidth;
					token = TextService.bringTextToWidth(metrics, token, 
							widthLeft );
					if ( line.equals( TextService.CUTTED_TEXT ) ) {
						line = line + TextService.CUTTED_TEXT;
					}
					else {
						line = line + BLANK + token;
					}
				}
				
				// finish line
				int x = MAX_TEXT_WIDTH - maxLineWidth + 10;
				TextLine textLine = new TextLine( line, x );
				lineList.add( textLine );
				
				if ( noMoreLines ) {
					break;
				}
				else {
					// prepate new line
					lineIndex++;
					maxLineWidth = lineWidths[ lineIndex ];
					line = token;
					if ( ! tokenizer.hasMoreTokens() ) {
						// regular end;
						x = MAX_TEXT_WIDTH - maxLineWidth + 10;
						textLine = new TextLine( line, x );
						lineList.add( textLine );
					}
				}
			}
		}
		
		TextLine[] textLines = lineList.toArray( new TextLine[0] );
		this.lines = textLines;
	}
	
	

	public String getTitle(){
		return title;
	}
	
	public TextLine[] getLines(){
		return lines;
	}

	public Font getTitleFont() {
		return titleFont;
	}

	public Font getTextFont() {
		return textFont;
	}


	public BufferedImage getImage() {
		return scaledImage;
	}
	
}
